home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 79 / maccd 79.iso / multimedial / GL Tron / Source / gltron / gamegraphics.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-07-10  |  21.7 KB  |  851 lines  |  [TEXT/CWIE]

  1. #include "gltron.h"
  2.  
  3. static float arena[] = { 1.0, 1.2, 1, 0.0 };
  4.  
  5. void drawGame() {
  6.   GLint i;
  7.   gDisplay *d;
  8.   Player *p;
  9.  
  10.   polycount = 0;
  11.  
  12.   glEnable(GL_DEPTH_TEST);
  13.  
  14.   glClearColor(.0, .0, .0, .0);
  15.   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  16.  
  17.   for(i = 0; i < vp_max[ game->settings->display_type]; i++) {
  18.     p = &(game->player[ game->settings->content[i] ]);
  19.     if(p->display->onScreen == 1) {
  20.       d = p->display;
  21.       glViewport(d->vp_x, d->vp_y, d->vp_w, d->vp_h);
  22.       drawCam(p, d);
  23.       glDisable(GL_DEPTH_TEST);
  24.       glDepthMask(GL_FALSE);
  25.       drawScore(p, d);
  26.       if(game->settings->show_ai_status)
  27.     if(p->ai->active == 1)
  28.       drawAI(d);
  29.     }
  30.     glDepthMask(GL_TRUE);
  31.     glEnable(GL_DEPTH_TEST);
  32.   }
  33.  
  34.   if(game->settings->show_2d > 0) {
  35.     drawDebugTex(game->screen);
  36.     drawDebugLines(game->screen);
  37.   }
  38.   if(game->settings->show_fps)
  39.     drawFPS(game->screen);
  40.  
  41.   drawConsole(game->screen);
  42.   /*
  43.   if(game->settings->show_help == 1)
  44.     drawHelp(game->screen);
  45.   */
  46.  
  47.   /* printf("%d polys\n", polycount); */
  48. }
  49.  
  50. void checkGLError(char *where) {
  51.   int error;
  52.   error = glGetError();
  53.   if(error != GL_NO_ERROR)
  54.     printf("[glError: %s] - %d\n", where, error);
  55. }
  56.  
  57. void rasonly(gDisplay *d) {
  58.   /* do rasterising only (in local display d) */
  59.   glMatrixMode(GL_PROJECTION);
  60.   glLoadIdentity();
  61.   glOrtho(0.0f, (GLfloat) d->vp_w, 0.0f, (GLfloat) d->vp_h, 0.0f, 1.0f);
  62.   checkGLError("rasonly");
  63.   glMatrixMode(GL_MODELVIEW);
  64.   glLoadIdentity();
  65.   glViewport(d->vp_x, d->vp_y, d->vp_w, d->vp_h);
  66. }
  67.  
  68. void drawText(fonttex* ftx, int x, int y, int size, char *text) {
  69.   if(game->settings->softwareRendering) {
  70.     drawSoftwareText(ftx, x, y, size, text);
  71.   } else {
  72.     glEnable(GL_BLEND);
  73.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  74.     glEnable(GL_TEXTURE_2D);
  75.  
  76.     glPushMatrix();
  77.  
  78.     glTranslatef(x, y, 0);
  79.     glScalef(size, size, size);
  80.     ftxRenderString(ftx, text, strlen(text));
  81.   
  82.     glPopMatrix();
  83.     glDisable(GL_TEXTURE_2D);
  84.     glDisable(GL_BLEND);
  85.     polycount += 2 * strlen(text); /* quads are two triangles */
  86.   }
  87. }
  88.  
  89. void initModelLights(int light) {
  90.   /* float col[] = { .77, .77, .77, 1.0 }; */
  91.   float col[] = { .95, .95, .95, 1.0 };
  92.   float dif[] =  { 0.4, 0.4, 0.4, 1};
  93.   float amb[] = { 0.05, 0.05, 0.05, 1};
  94.  
  95.   glLightfv(light, GL_AMBIENT, amb);
  96.   glLightfv(light, GL_SPECULAR, col);
  97.   glLightfv(light, GL_DIFFUSE, dif);
  98.   
  99. }
  100.  
  101. void initTrailLights(int light) {
  102.   /* doing my own lighting for that now */
  103.   /* int light is currently ignored */
  104.   float amb[] = { 0.2, 0.2, 0.2, 1};
  105.   setFactor3fv(amb);
  106.   setLight4fv(arena);
  107. }
  108.  
  109. void rebuildDebugTex() {
  110.   int x, y;
  111.   int px = -1, py = -1;
  112.   float tx, ty;
  113.   int color;
  114.   unsigned char *source;
  115.   /* printf("rebuilding texture: %d -> ", SystemGetElapsedTime()); */
  116.   for(y = 0; y < game->settings->grid_size; y++) {
  117.     ty = (float) y * DEBUG_TEX_H / game->settings->grid_size;
  118.     for(x = 0; x < game->settings->grid_size; x++) {
  119.       tx = (float) x * DEBUG_TEX_W / game->settings->grid_size;
  120.       color = colmap [ y * colwidth + x];
  121.       if(color != 0 || ((int)tx != px && (int)ty != py)) {
  122.     px = (int) tx; 
  123.     source = debugcolors[ color ];
  124.     memcpy(debugtex + (int)ty * DEBUG_TEX_W * 4 + px * 4, source, 4);
  125.       }
  126.     }
  127.     py = (int)ty;
  128.   }
  129.   /* printf("%d\n", SystemGetElapsedTime()); */
  130. }
  131.  
  132. #define MAP_SIZE 256.0
  133.  
  134. void drawDebugLines(gDisplay *d) {
  135.   int i;
  136.   Player *p;
  137.   Data *data;
  138.   line *line;
  139.   int size;
  140.   float scale;
  141.  
  142.   rasonly(d);
  143.   glTranslatef(10, 400, 0);
  144.   size = game->settings->grid_size;
  145.  
  146.   scale = MAP_SIZE / size;
  147.  
  148.   glPushMatrix();
  149.  
  150.   glScalef(scale, scale, scale);
  151.   glColor3f(1.0, 1.0, 1.0);
  152.   glBegin(GL_LINE_LOOP);
  153.   glVertex2i(0, 0);
  154.   glVertex2i(size, 0);
  155.   glVertex2i(size, size);
  156.   glVertex2i(0, size);
  157.   glEnd();
  158.  
  159.   /* glLineWidth(2); */ /* buggy in Mesa/Glide */
  160.   for(i = 0; i < game->players; i++) {
  161.     p = &(game->player[i]);
  162.     data = p->data;
  163.     if(data->speed > 0) {
  164.       glBegin(GL_LINES);
  165.       glColor3fv(p->model->color_alpha);
  166.       line = &(data->trails[0]);
  167.       while(line != data->trail) {
  168.  
  169.     glVertex2f(line->sx, line->sy);
  170.     glVertex2f(line->ex, line->ey);
  171.     line++;
  172.     polycount++;
  173.       }
  174.       glVertex2f(line->sx, line->sy);
  175.       glVertex2f(data->posx, data->posy);
  176.       glEnd();
  177.     }
  178.   }
  179.   /* glLineWidth(1); */
  180.   glPopMatrix();
  181. }
  182.  
  183. void drawDebugTex(gDisplay *d) {
  184.   glDisable(GL_DEPTH_TEST);
  185.   /* build2DTex(); */
  186.   /* fprintf(stderr, "%d ", SystemGetElapsedTime()); */
  187.   rasonly(d);
  188.   glTranslatef(10, 100, 0);
  189.  
  190.   glEnable(GL_BLEND);
  191.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  192.  
  193.   /*
  194.   glBegin(GL_QUADS);
  195.   glColor4f(1.0, 1.0, 1.0, 0.1);
  196.   glTexCoord2f(0.0, 0.0); glVertex2i(0, 0);
  197.   glTexCoord2f(1.0, 0.0); glVertex2i(255, 0);
  198.   glTexCoord2f(1.0, 1.0); glVertex2i(255, 255);
  199.   glTexCoord2f(0.0, 1.0); glVertex2i(0, 255);  
  200.   glEnd();
  201.   */
  202.  
  203.   glEnable(GL_TEXTURE_2D);
  204.   glBindTexture(GL_TEXTURE_2D, d->textures[TEX_DEBUG]);
  205.   if(ogl_debugtex == 0) {
  206.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DEBUG_TEX_W, DEBUG_TEX_H, 
  207.          0, GL_RGBA, GL_UNSIGNED_BYTE, debugtex);
  208.     ogl_debugtex = 1;
  209.   } else {
  210.     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, DEBUG_TEX_W, DEBUG_TEX_H, GL_RGBA,
  211.          GL_UNSIGNED_BYTE, debugtex);
  212.   }
  213.  
  214.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  215.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  216.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  217.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  218.   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  219.  
  220.   glBlendFunc(GL_ONE, GL_ONE);
  221.   glBegin(GL_QUADS);
  222.   glColor3f(1.0, 1.0, 1.0);
  223.   glTexCoord2f(0.0, 0.0); glVertex2i(0, 0);
  224.   glTexCoord2f(1.0, 0.0); glVertex2i(255, 0);
  225.   glTexCoord2f(1.0, 1.0); glVertex2i(255, 255);
  226.   glTexCoord2f(0.0, 1.0); glVertex2i(0, 255);  
  227.   glEnd();
  228.  
  229.   glDisable(GL_TEXTURE_2D);
  230.  
  231.   glBegin(GL_LINE_LOOP);
  232.   glVertex2i(0, 0);
  233.   glVertex2i(255, 0);
  234.   glVertex2i(255, 255);
  235.   glVertex2i(0, 255);
  236.   glEnd();
  237.  
  238.       /*
  239.   int x = 100;
  240.   int y = 100;
  241.  
  242.   rasonly(d);
  243.   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  244.   glColor4f(.0, 1.0, .0, 1.0);
  245.   glRasterPos2i(x, y);
  246.   glBitmap(colwidth * 8 , game->settings->grid_size, 0, 0, 0, 0, colmap);
  247.   glBegin(GL_LINE_LOOP);
  248.   glVertex2i(x - 1, y - 1);
  249.   glVertex2i(x + colwidth * 8, y - 1);
  250.   glVertex2i(x + colwidth * 8, y + game->settings->grid_size);
  251.   glVertex2i(x - 1, y + game->settings->grid_size);
  252.   glEnd();
  253.   polycount += 4;
  254.   */
  255.   /* fprintf(stderr, "%d\n", SystemGetElapsedTime()); */
  256.   glEnable(GL_DEPTH_TEST);
  257. }
  258.  
  259. void drawConsoleLines(char *line, int call) {
  260. #define CONSOLE_SIZE 15
  261. #define CONSOLE_X_OFF 20
  262.   int size = CONSOLE_SIZE;
  263.   int length;
  264.   /* fprintf(stdout, "%s\n", line); */
  265.   length = strlen(line);
  266.   while(length * size > game->screen->vp_w / 2 - CONSOLE_X_OFF)
  267.     size--;
  268.     
  269.   if(*line != 0) 
  270.     drawText(gameFtx, CONSOLE_X_OFF, game->screen->vp_h - 20 * (call + 1),
  271.          size, line);
  272. }
  273.  
  274. void drawConsole(gDisplay *d) {
  275.   int lines = 5;
  276.   rasonly(d);
  277.   glColor3f(1.0, 0.3, 0.3);
  278.   if(game->screen->vp_h < 600) lines = 3;
  279.   if(game->settings->softwareRendering) lines = 1;
  280.   consoleDisplay(drawConsoleLines, lines);
  281. }
  282.   
  283. void drawFPS(gDisplay *d) {
  284. #define FPS_HSIZE 20
  285.   /* draws FPS in upper left corner of Display d */
  286.   static int fps_h[FPS_HSIZE];
  287.   static int pos = -FPS_HSIZE;
  288.   static int fps_min = 0;
  289.   static int fps_avg = 0;
  290.  
  291.   char tmp[20];
  292.   int diff;
  293.  
  294.   rasonly(d);
  295.   diff = (game2->time.dt > 0) ? game2->time.dt : 1;
  296.  
  297.   if(pos < 0) {
  298.     fps_avg = 1000 / diff;
  299.     fps_min = 1000 / diff;
  300.     fps_h[pos + FPS_HSIZE] = 1000 / diff;
  301.     pos++;
  302.   } else {
  303.     fps_h[pos] = 1000 / diff;
  304.     pos = (pos + 1) % FPS_HSIZE;
  305.     if(pos % 10 == 0) {
  306.       int i;
  307.       int sum = 0;
  308.       int min = 1000;
  309.       for(i = 0; i < FPS_HSIZE; i++) {
  310.     sum += fps_h[i];
  311.     if(fps_h[i] < min)
  312.       min = fps_h[i];
  313.       }
  314.       fps_min = min;
  315.       fps_avg = sum / FPS_HSIZE;
  316.     }
  317.   }
  318.  
  319.   sprintf(tmp, "average FPS: %d", fps_avg);
  320.   glColor4f(1.0, 0.4, 0.2, 1.0);
  321.   drawText(gameFtx, d->vp_w - 180, d->vp_h - 20, 10, tmp);
  322.   sprintf(tmp, "minimum FPS: %d", fps_min);
  323.   drawText(gameFtx, d->vp_w - 180, d->vp_h - 35, 10, tmp);
  324.   sprintf(tmp, "triangles: %d", polycount);
  325.   drawText(gameFtx, d->vp_w - 180, d->vp_h - 50, 10, tmp);
  326. }
  327.  
  328. void drawScore(Player *p, gDisplay *d) {
  329.   char tmp[10]; /* hey, they won't reach such a score */
  330.  
  331.   sprintf(tmp, "%d", p->data->score);
  332.   rasonly(d);
  333.   glColor4f(1.0, 1.0, 0.2, 1.0);
  334.   drawText(gameFtx, 5, 5, 32, tmp);
  335. }
  336.   
  337. void drawFloor(gDisplay *d) {
  338.   int j, k, l, t;
  339.  
  340.  
  341.  
  342.   if(game->settings->show_floor_texture) {
  343.     glEnable(GL_BLEND);
  344.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  345.     glEnable(GL_TEXTURE_2D);
  346.     glBindTexture(GL_TEXTURE_2D, game->screen->textures[TEX_FLOOR]);
  347.     /* there are some strange clipping artefacts in software mode */
  348.     /* try subdividing things... */
  349.     glColor4f(1.0, 1.0, 1.0, 1.0);
  350.     l = game->settings->grid_size / 4;
  351.     t = l / 12;
  352.     for(j = 0; j < game->settings->grid_size; j += l)
  353.       for(k = 0; k < game->settings->grid_size; k += l) {
  354.     glBegin(GL_QUADS);
  355.     glTexCoord2i(0, 0);
  356.     glVertex2i(j, k);
  357.     glTexCoord2i(t, 0);
  358.     glVertex2i(j + l, k);
  359.     glTexCoord2i(t, t);
  360.     glVertex2i(j + l, k + l);
  361.     glTexCoord2i(0, t);
  362.     glVertex2i(j, k + l);
  363.     glEnd();
  364.     polycount += 2;
  365.       }
  366.     glDisable(GL_TEXTURE_2D);
  367.   } else {
  368.     /* lines as floor... */
  369.     glColor3f(0.0, 0.0, 1.0);
  370.     glBegin(GL_LINES);
  371.     for(j = 0; j <= game->settings->grid_size;
  372.     j += game->settings->line_spacing) {
  373.       glVertex3i(0, j, 0);
  374.       glVertex3i(game->settings->grid_size, j, 0);
  375.       glVertex3i(j, 0, 0);
  376.       glVertex3i(j, game->settings->grid_size, 0);
  377.       polycount += 2;
  378.     }
  379.     glEnd();
  380.   }
  381.  
  382.   glShadeModel( game->screen->shademodel );
  383. }
  384.  
  385. void drawCrash(float radius) {
  386. #define CRASH_W 32
  387. #define CRASH_H 16
  388.   glDisable(GL_DEPTH_TEST);
  389.   glDepthMask(GL_FALSE);
  390.   glColor4f(1.0, 1.0, 1.0, (EXP_RADIUS_MAX - radius) / EXP_RADIUS_MAX);
  391.   /* printf("exp_r: %.2f\n", (EXP_RADIUS_MAX - radius) / EXP_RADIUS_MAX); */
  392.   glEnable(GL_TEXTURE_2D);
  393.   glBindTexture(GL_TEXTURE_2D, game->screen->textures[TEX_CRASH]);
  394.   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  395.   glEnable(GL_BLEND);
  396.   glBegin(GL_QUADS);
  397.   glTexCoord2f(0.0, 0.0);
  398.   glVertex3f(- CRASH_W / 2, 0.0, 0.0);
  399.   glTexCoord2f(1.0, 0.0);
  400.   glVertex3f(CRASH_W / 2, 0.0, 0.0);
  401.   glTexCoord2f(1.0, 1.0);
  402.   glVertex3f(CRASH_W / 2, 0.0, CRASH_H);
  403.   glTexCoord2f(0.0, 1.0);
  404.   glVertex3f(- CRASH_W / 2, 0.0, CRASH_H);
  405.   glEnd();
  406.  
  407.   polycount += 2;
  408.  
  409.   glDisable(GL_TEXTURE_2D);
  410.   glEnable(GL_DEPTH_TEST);
  411.   glDepthMask(GL_TRUE);
  412. }
  413.  
  414. void drawCycle(Player *p, int lod) {
  415.   float dirangles1[] = { 180, 90, 0, 270, 360, -90 };
  416.   float dirangles2[] = { 0, -90, -180, 90, 180, -270 };
  417.   float *dirangles;
  418.   int neigung_dir;
  419.   int time = 0;
  420.   int last_dir;
  421.   float dirangle;
  422.   Mesh *cycle;
  423.  
  424.   dirangles = dirangles2;
  425.   neigung_dir = -1.0;
  426.  
  427.   if(game->settings->model_backwards) {
  428.      dirangles = dirangles1;
  429.      neigung_dir = 1.0;
  430.   }
  431.  
  432.   cycle = p->model->mesh[lod];
  433.     
  434.   glPushMatrix();
  435.   glTranslatef(p->data->posx, p->data->posy, 0.0);
  436.  
  437.   if(game->settings->turn_cycle) {
  438.     time = game2->time.current - p->data->turn_time;
  439.     if(time < TURN_LENGTH) {
  440.       last_dir = p->data->last_dir;
  441.       if(p->data->dir == 3 && last_dir == 2)
  442.     last_dir = 4;
  443.       if(p->data->dir == 2 && last_dir == 3)
  444.     last_dir = 5;
  445.       dirangle = ((TURN_LENGTH - time) * dirangles[last_dir] +
  446.           time * dirangles[p->data->dir]) / TURN_LENGTH;
  447.     } else
  448.       dirangle = dirangles[p->data->dir];
  449.   } else  dirangle = dirangles[p->data->dir];
  450.  
  451.   glRotatef(dirangle, 0.0, 0.0, 1.0);
  452.  
  453.   if(game->settings->show_crash_texture) {
  454.     if(p->data->exp_radius > 0 && p->data->exp_radius < EXP_RADIUS_MAX) {
  455.       glPushMatrix();
  456.       glRotatef(dirangles[p->data->dir] - dirangle, 0.0, 0.0, 1.0);
  457.       drawCrash(p->data->exp_radius);
  458.       glPopMatrix();
  459.     }
  460.   }
  461.  
  462. #define neigung 25
  463.   if(game->settings->turn_cycle) {
  464.     if(time < TURN_LENGTH) {
  465.       float axis = 1.0;
  466.       if(p->data->dir < p->data->last_dir && p->data->last_dir != 3)
  467.     axis = -1.0;
  468.       else if((p->data->last_dir == 3 && p->data->dir == 2) ||
  469.           (p->data->last_dir == 0 && p->data->dir == 3))
  470.     axis = -1.0;
  471.       glRotatef(neigung * sin(M_PI * time / TURN_LENGTH),
  472.         0.0, axis * neigung_dir, 0.0);
  473.     }
  474.   }
  475.  
  476.   glTranslatef(-cycle->bbox[0] / 2, -cycle->bbox[1] / 2, .0);
  477.   /* glTranslatef(-cycle->bbox[0] / 2, 0, .0); */
  478.   /* glTranslatef(-cycle->bbox[0] / 2, -cycle->bbox[1], .0); */
  479.  
  480.   initModelLights(GL_LIGHT1);
  481.   glDisable(GL_LIGHT0);
  482.   glEnable(GL_LIGHT1);
  483.   glDisable(GL_COLOR_MATERIAL);
  484.   if(game->settings->light_cycles)
  485.     glEnable(GL_LIGHTING);
  486.   glEnable(GL_CULL_FACE);
  487.   glEnable(GL_DEPTH_TEST);
  488.   glDepthMask(GL_TRUE);
  489.  
  490.   if(p->data->exp_radius == 0)
  491.     drawModel(cycle, MODEL_USE_MATERIAL, 0);
  492.   else if(p->data->exp_radius < EXP_RADIUS_MAX) {
  493.     float alpha;
  494.     if(game->settings->show_alpha == 1) {
  495.       glEnable(GL_BLEND);
  496.       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  497.       alpha = (float) (EXP_RADIUS_MAX - p->data->exp_radius) /
  498.     (float) EXP_RADIUS_MAX;
  499.       setMaterialAlphas(cycle, alpha);
  500.     }
  501.     drawExplosion(cycle, p->data->exp_radius, MODEL_USE_MATERIAL, 0);
  502.   }
  503.   glDisable(GL_BLEND);
  504.   glDisable(GL_LIGHTING);
  505.   glDisable(GL_CULL_FACE);
  506.   glPopMatrix();
  507. }
  508.  
  509. static int lod_dist[][4] = { 
  510.   { 25, 50, 150, 0 },
  511.   { 5, 30, 150, 0 },
  512.   { 1, 5, 100, 0 }
  513. };
  514. static int max_lod = 2;
  515.  
  516. int playerVisible(Player *eye, Player *target) {
  517.   float v1[3];
  518.   float v2[3];
  519.   float tmp[3];
  520.   float s;
  521.   float d;
  522.   int i;
  523.   int lod;
  524.  
  525.   vsub(eye->camera->target, eye->camera->cam, v1);
  526.   normalize(v1);
  527.   tmp[0] = target->data->posx;
  528.   tmp[1] = target->data->posy;
  529.   tmp[2] = 0;
  530.   vsub(tmp, eye->camera->cam, v2);
  531.   normalize(v2);
  532.   s = scalarprod(v1, v2);
  533.   /* maybe that's not exactly correct, but I didn't notice anything */
  534.   d = cos((game->settings->fov / 2) * 2 * M_PI / 360.0);
  535.   /*
  536.   printf("v1: %.2f %.2f %.2f\nv2: %.2f %.2f %.2f\ns: %.2f d: %.2f\n\n",
  537.      v1[0], v1[1], v1[2], v2[0], v2[1], v2[2],
  538.      s, d);
  539.   */
  540.   if(s < d)
  541.     return -1;
  542.   else {
  543.     lod = (game->settings->lod > max_lod) ? max_lod : game->settings->lod;
  544.     /* calculate lod */
  545.     vsub(eye->camera->cam, tmp, v1);
  546.     d = length(v1);
  547.     for(i = 0; i < target->model->lod; i++) {
  548.       if(d < lod_dist[lod][i])
  549.     return i;
  550.     }
  551.     return -1;
  552.   }
  553. }
  554.         
  555. void drawPlayers(Player *p) {
  556.   int i;
  557.   float height;
  558.   int lod;
  559.  
  560.   glShadeModel(GL_SMOOTH);
  561.   for(i = 0; i < game->players; i++) {
  562.     height = game->player[i].data->trail_height;
  563.  
  564.     if(game->settings->show_model) {
  565.       lod = playerVisible(p, &(game->player[i]));
  566.       if(lod >= 0) 
  567.     drawCycle(&(game->player[i]), lod);
  568.     }
  569.   }
  570.   glShadeModel( game->screen->shademodel );
  571. }
  572.  
  573. void drawGlow(Player *p, gDisplay *d, float dim) {
  574.   float mat[4*4];
  575.   
  576.   glPushMatrix();
  577.   glTranslatef(p->data->posx,
  578.                p->data->posy,
  579.                0);
  580.  
  581.   glShadeModel(GL_SMOOTH);
  582.  
  583.   glDepthMask(GL_FALSE);
  584.   glDisable(GL_DEPTH_TEST);
  585.  
  586.   glBlendFunc(GL_ONE, GL_ONE);
  587.   glEnable(GL_BLEND);
  588.  
  589.   glGetFloatv(GL_MODELVIEW_MATRIX, mat);
  590.   mat[0] = mat[5] = mat[10] = 1.0;
  591.   mat[1] = mat[2] = 0.0;
  592.   mat[4] = mat[6] = 0.0;
  593.   mat[8] = mat[9] = 0.0;
  594.   glLoadMatrixf(mat);
  595.   glBegin(GL_TRIANGLE_FAN);
  596.   glColor3fv(p->model->color_model);
  597.  
  598.   glVertex3f(0,TRAIL_HEIGHT/2, 0);
  599.   glColor4f(0,0,0,0.0);
  600.   glVertex3f(dim*cos(-0.2*3.1415/5.0),
  601.          TRAIL_HEIGHT/2+dim*sin(-0.2*3.1415/5.0), 0);
  602.   glVertex3f(dim*cos(1.0*3.1415/5.0),
  603.          TRAIL_HEIGHT/2+dim*sin(1.0*3.1415/5.0), 0);
  604.   glVertex3f(dim*cos(2.0*3.1415/5.0),
  605.          TRAIL_HEIGHT/2+dim*sin(2.0*3.1415/5.0), 0);
  606.   glVertex3f(dim*cos(3.0*3.1415/5.0),
  607.          TRAIL_HEIGHT/2+dim*sin(3.0*3.1415/5.0), 0);
  608.   glVertex3f(dim*cos(4.0*3.1415/5.0),
  609.          TRAIL_HEIGHT/2+dim*sin(4.0*3.1415/5.0), 0);
  610.   glVertex3f(dim*cos(5.2*3.1415/5.0),
  611.          TRAIL_HEIGHT/2+dim*sin(5.2*3.1415/5.0), 0);
  612.   glEnd();
  613.   polycount += 5;
  614.  
  615.  
  616.   glBegin(GL_TRIANGLES);
  617.   glColor3fv(p->model->color_model);
  618.   glVertex3f(0,TRAIL_HEIGHT/2, 0);
  619.   glColor4f(0,0,0,0.0);
  620.   glVertex3f(0,-TRAIL_HEIGHT/4,0);
  621.   glVertex3f(dim*cos(-0.2*3.1415/5.0),
  622.          TRAIL_HEIGHT/2+dim*sin(-0.2*3.1415/5.0), 0);
  623.  
  624.   glColor3fv(p->model->color_model);
  625.   glVertex3f(0,TRAIL_HEIGHT/2, 0);
  626.   glColor4f(0,0,0,0.0);
  627.   glVertex3f(dim*cos(5.2*3.1415/5.0),
  628.          TRAIL_HEIGHT/2+dim*sin(5.2*3.1415/5.0), 0);
  629.   glVertex3f(0,-TRAIL_HEIGHT/4,0);
  630.   glEnd();
  631.   polycount += 3;
  632.  
  633.   glDepthMask(GL_TRUE);
  634.   glEnable(GL_DEPTH_TEST);
  635.  
  636.   glShadeModel( game->screen->shademodel );
  637.   glPopMatrix();  
  638.  
  639.  
  640. }
  641.  
  642. void drawWalls(gDisplay *d) {
  643. #undef WALL_H
  644. #define WALL_H 48
  645.   float t;
  646.   float h;
  647.  
  648.   t = game->settings->grid_size / 240.0;
  649.   if(game->settings->stretch_textures) {
  650.     h = t * WALL_H;
  651.     t = 1.0;
  652.   } else h = WALL_H;
  653.  
  654.   glColor4f(1.0, 1.0, 1.0, 1.0);
  655.  
  656.  
  657.   glEnable(GL_BLEND);
  658.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  659.   glEnable(GL_CULL_FACE);
  660.   glEnable(GL_TEXTURE_2D);
  661. #define T_TOP 1.0
  662.   glBindTexture(GL_TEXTURE_2D, game->screen->textures[TEX_WALL1]);
  663.   glBegin(GL_QUADS);
  664.     glTexCoord2f(t, 0.0); glVertex3f(0.0, 0.0, 0.0);
  665.     glTexCoord2f(t, T_TOP); glVertex3f(0.0, 0.0, h);
  666.     glTexCoord2f(0.0, T_TOP); glVertex3f(game->settings->grid_size, 0.0, h);
  667.     glTexCoord2f(0.0, 0.0); glVertex3f(game->settings->grid_size, 0.0, 0.0);
  668.   glEnd();
  669.   
  670.   glBindTexture(GL_TEXTURE_2D, game->screen->textures[TEX_WALL2]);
  671.   glBegin(GL_QUADS);
  672.     glTexCoord2f(t, 0.0); glVertex3f(game->settings->grid_size, 0.0, 0.0);
  673.     glTexCoord2f(t, T_TOP); glVertex3f(game->settings->grid_size, 0.0, h);
  674.     glTexCoord2f(0.0, T_TOP); 
  675.     glVertex3f(game->settings->grid_size, game->settings->grid_size, h);
  676.     glTexCoord2f(0.0, 0.0); 
  677.     glVertex3f(game->settings->grid_size, game->settings->grid_size, 0.0);
  678.   glEnd();
  679.   
  680.   glBindTexture(GL_TEXTURE_2D, game->screen->textures[TEX_WALL3]);
  681.   glBegin (GL_QUADS);
  682.   glTexCoord2f(t, 0.0); 
  683.     glVertex3f(game->settings->grid_size, game->settings->grid_size, 0.0);
  684.     glTexCoord2f(t, T_TOP); 
  685.     glVertex3f(game->settings->grid_size, game->settings->grid_size, h);
  686.     glTexCoord2f(0.0, T_TOP); glVertex3f(0.0, game->settings->grid_size, h);
  687.     glTexCoord2f(0.0, 0.0); glVertex3f(0.0, game->settings->grid_size, 0.0);
  688.   glEnd();
  689.   
  690.   glBindTexture(GL_TEXTURE_2D, game->screen->textures[TEX_WALL4]);
  691.   glBegin(GL_QUADS);
  692.     glTexCoord2f(t, 0.0); glVertex3f(0.0, game->settings->grid_size, 0.0);
  693.     glTexCoord2f(t, T_TOP); glVertex3f(0.0, game->settings->grid_size, h);
  694.     glTexCoord2f(0.0, T_TOP); glVertex3f(0.0, 0.0, h);
  695.     glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0, 0.0); 
  696.     #undef T_TOP
  697.   glEnd();
  698.   polycount += 8;
  699.  
  700.   glDisable(GL_TEXTURE_2D);
  701.  
  702.   glDisable(GL_CULL_FACE);
  703. }
  704.  
  705.  
  706. void doPerspective(float fov, float ratio, float znear, float zfar) {
  707.   float top;
  708.   float left;
  709.  
  710.   top = tan( fov * M_PI / 360.0 ) * znear;
  711.   left = - top * ratio;
  712.   glFrustum(left, -left, -top, top, znear, zfar);
  713. }
  714.  
  715. void doLookAt(float *cam, float *target, float *up) {
  716.   float m[16];
  717.   float x[3], y[3], z[3];
  718.  
  719.   vsub(cam, target, z);
  720.   normalize(z);
  721.   crossprod(up, z, x);
  722.   crossprod(z, x, y);
  723.   normalize(x);
  724.   normalize(y);
  725.  
  726. #define M(row,col)  m[col*4+row]
  727.    M(0,0) = x[0];  M(0,1) = x[1];  M(0,2) = x[2];  M(0,3) = 0.0;
  728.    M(1,0) = y[0];  M(1,1) = y[1];  M(1,2) = y[2];  M(1,3) = 0.0;
  729.    M(2,0) = z[0];  M(2,1) = z[1];  M(2,2) = z[2];  M(2,3) = 0.0;
  730.    M(3,0) = 0.0;   M(3,1) = 0.0;   M(3,2) = 0.0;   M(3,3) = 1.0;
  731. #undef M
  732.    glMultMatrixf( m );
  733.  
  734.    /* Translate Eye to Origin */
  735.    glTranslatef( -cam[0], -cam[1], -cam[2]);
  736. }
  737.  
  738.  
  739. void drawCam(Player *p, gDisplay *d) {
  740.   int i;
  741.   float up[3] = { 0, 0, 1 };
  742.   /* 
  743.   if (d->fog == 1) {
  744.     glEnable(GL_FOG);
  745.     fprintf(stderr, "who enabled the fog?\n");
  746.   }
  747.   */
  748.  
  749.   glColor3f(0.0, 1.0, 0.0);
  750.   glMatrixMode(GL_PROJECTION);
  751.   glLoadIdentity();
  752.   doPerspective(game->settings->fov, d->vp_w / d->vp_h,
  753.          game->settings->znear, game->settings->grid_size * 6.5);
  754.  
  755.   glMatrixMode(GL_MODELVIEW);
  756.   glLoadIdentity();
  757.   /* set positions for GL lights in world coordinates */
  758.   glLightfv(GL_LIGHT1, GL_POSITION, p->camera->cam);
  759.  
  760.   doLookAt(p->camera->cam, p->camera->target, up);
  761.  
  762.   glDisable(GL_LIGHTING);
  763.  
  764.   if(game->settings->show_skybox)
  765.     skybox();
  766.  
  767.   drawFloor(d);
  768.   for(i = 0; i < game->players; i++)
  769.     drawTrailShadow(game->player[i].data);
  770.  
  771.   if(game->settings->show_wall == 1)
  772.     drawWalls(d);
  773.  
  774.   glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
  775.   glEnable(GL_COLOR_MATERIAL);
  776.   glShadeModel(GL_SMOOTH);
  777.   drawPlayers(p);
  778.  
  779.   glEnable(GL_BLEND);
  780.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  781.   // glDepthMask(GL_FALSE);
  782.   initTrailLights(0);
  783.   doTrails(p);
  784.   // glDepthMask(GL_TRUE);
  785.   for(i = 0; i < game->players; i++) {
  786.     // drawTraces(&(game->player[i]), d);
  787.     drawTrailLines(&(game->player[i]));
  788.   }
  789.  
  790.  
  791.   /* transparent stuff */
  792.   /* for(i = 0; i < game->players; i++)
  793.      drawTrailBow(&(game->player[i])); */
  794.  
  795.   /* draw the glow around the other players: */
  796.   if(game->settings->show_glow == 1)
  797.     for(i = 0; i < game->players; i++)
  798.       if ((p != &(game->player[i])) && (game->player[i].data->speed > 0))
  799.     drawGlow(&(game->player[i]), d, TRAIL_HEIGHT * 4);
  800. }
  801.  
  802. void drawAI(gDisplay *d) {
  803.   char ai[] = "computer player";
  804.  
  805.   rasonly(d);
  806.   glColor3f(1.0, 1.0, 1.0);
  807.   drawText(gameFtx, d->vp_w / 4, 10, d->vp_w / (2 * strlen(ai)), ai);
  808.   /* glRasterPos2i(100, 0); */
  809. }
  810.  
  811. void drawPause(gDisplay *display) {
  812.   char pause[] = "Game is paused";
  813.   char winner[] = "Player %d wins!";
  814.   char buf[100];
  815.   char *message;
  816.   static float d = 0;
  817.   static float lt = 0;
  818.   float delta;
  819.   long now;
  820.  
  821.   now = SystemGetElapsedTime();
  822.   delta = now - lt;
  823.   lt = now;
  824.   delta /= 500.0;
  825.   d += delta;
  826.   /* printf("%.5f\n", delta); */
  827.   
  828.   if(d > 2 * M_PI) { 
  829.     d -= 2 * M_PI;
  830.   }
  831.  
  832.   if((game->pauseflag & PAUSE_GAME_FINISHED) &&
  833.      game->winner != -1) {
  834.     message = buf;
  835.     sprintf(message, winner, game->winner + 1);
  836.   } else {
  837.     message = pause;
  838.   }
  839.  
  840.   rasonly(game->screen);
  841.   glColor3f(1.0, (sin(d) + 1) / 2, (sin(d) + 1) / 2);
  842.   drawText(gameFtx, display->vp_w / 6, 20, 
  843.        display->vp_w / (6.0 / 4.0 * strlen(message)), message);
  844. }
  845.  
  846. void initGLGame() {
  847.   glShadeModel( game->screen->shademodel );
  848.   glDepthMask(GL_TRUE);
  849.   glEnable(GL_DEPTH_TEST);
  850. }
  851.